package com.mzw.project.service.impl;

import cn.hutool.http.HttpStatus;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mzw.mzwcommon.model.entity.UserInterfaceInfo;

import com.mzw.project.common.BaseResponse;
import com.mzw.project.common.ErrorCode;
import com.mzw.project.common.ResultUtils;
import com.mzw.project.exception.BusinessException;
import com.mzw.project.mapper.UserInterfaceInfoMapper;

import com.mzw.project.mapper.VoucherOrderMapper;
import com.mzw.project.model.entity.Voucher;
import com.mzw.project.model.entity.VoucherOrder;
import com.mzw.project.service.InterfaceInfoService;
import com.mzw.project.service.UserInterfaceInfoService;
import com.mzw.project.service.VoucherOrderService;
import com.mzw.project.service.VoucherService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.concurrent.TimeUnit;

/**
 * @author L1nAn
 * @description 针对表【user_interface_info(用户调用接口关系表)】的数据库操作Service实现
 * @createDate 2023-06-25 09:13:36
 */
@Service
@Slf4j
public class UserInterfaceInfoServiceImpl extends ServiceImpl<UserInterfaceInfoMapper, UserInterfaceInfo>
        implements UserInterfaceInfoService {

    @Resource
    private RedissonClient redissonClient;


    @Override
    public void validUserInterfaceInfo(UserInterfaceInfo userInterfaceInfo, boolean add) {
        if (userInterfaceInfo == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        // 创建时，所有参数必须非空
        if (add) {
            if (userInterfaceInfo.getInterfaceInfoId() <= 0 || userInterfaceInfo.getUserId() <= 0) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "接口或用户不存在");
            }
        }
        if (userInterfaceInfo.getLeftNum() <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "剩余次数不能小于0");
        }
    }

    @Override
    public boolean invokeCount(long interfaceInfoId, long userId) {

        // 判断
        if (interfaceInfoId <= 0 || userId <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        UpdateWrapper<UserInterfaceInfo> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("interfaceInfoId", interfaceInfoId);
        updateWrapper.eq("userId", userId);
        updateWrapper.setSql("leftNum = leftNum - 1, totalNum = totalNum + 1");
        UpdateWrapper<UserInterfaceInfo> updateWrapper1 = new UpdateWrapper<>();
        updateWrapper1.eq("interfaceInfoId", interfaceInfoId);
        updateWrapper1.eq("userId", userId);
        updateWrapper1.setSql("freeLeftNum = freeLeftNum - 1, totalNum = totalNum + 1");
        RLock lock = redissonClient.getLock(String.valueOf(userId));
        Boolean flag = null;
        try {
            if (lock.tryLock()) {
                QueryWrapper<UserInterfaceInfo> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("userId", userId);
                queryWrapper.eq("interfaceInfoId", interfaceInfoId);
                if (this.getOne(queryWrapper).getFreeLeftNum() >= 1) {
                    flag = this.update(updateWrapper1);
                } else {
                    if (this.getOne(queryWrapper).getLeftNum() < 1) {
                        throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
                    }
                    flag = this.update(updateWrapper);
                    if (!flag) {
                        throw new BusinessException(ErrorCode.OPERATION_ERROR);
                    }
                }
            }
        } catch (BusinessException e) {
            throw new RuntimeException(e);
        } finally {
            lock.unlock();
        }
        return Boolean.TRUE.equals(flag);
//        return this.update(updateWrapper);

//        RLock redisLock = redissonClient.getLock("lock:interfaceInfoId:" + userId);
//        boolean isLock = redisLock.tryLock();
//        if (!isLock) {
//            log.error("不能同时重复调用接口");
//            throw new BusinessException(ErrorCode.PARAMS_ERROR, "不能同时重复调用接口");
//        }
//        boolean flag;
//        try {
//            UserInterfaceInfo userInterfaceInfo = this.getById(userId);
//            Integer leftNum = userInterfaceInfo.getLeftNum();
//            if (leftNum <= 0) {
//                throw new BusinessException(ErrorCode.PARAMS_ERROR, "接口没有调用次数");
//            }
        // leftNum 应该是大于0的/这的话判断在伙伴匹配系统中讲过，如果想要了解就去看那个项目
//        updateWrapper.gt("leftNum", 0);
//        RLock redisLock = redissonClient.getLock("lock:interfaceInfoId:" + userId);
        // 尝试获取锁
//            updateWrapper.setSql("leftNum = leftNum - 1, totalNum = totalNum + 1");
//            flag = this.update(updateWrapper);
//        } finally {
//            redisLock.unlock();
//        }
//        return flag;
//    }


//        updateWrapper.setSql("leftNum = leftNum - 1, totalNum = totalNum + 1");
//        return this.update(updateWrapper);

//        RLock lock = redissonClient.getLock("lock:interfaceInfoId:" + userId);
//        try {
//            // 抢到锁并执行
//            while (true) {
//                if (lock.tryLock(0, -1, TimeUnit.MILLISECONDS)) {
//                    System.out.println("getLock" + Thread.currentThread().getId());
//                    UserInterfaceInfo userInterfaceInfo = this.getById(userId);
//                    Integer leftNum = userInterfaceInfo.getLeftNum();
//                    if (leftNum <= 0) {
//                        throw new BusinessException(ErrorCode.PARAMS_ERROR, "接口调用次数已用完");
//                    }
//                    // 修改接口调用与剩余次数
//                    updateWrapper.setSql("leftNum = leftNum - 1, totalNum = totalNum + 1");
//                    return this.update(updateWrapper);
//                }
//            }
//        } catch (InterruptedException e) {
//            log.error("doCacheRecommendUser error", e);
//            return false;
//        } finally {
//            // 只能释放自己的锁
//            if (lock.isHeldByCurrentThread()) {
//                System.out.println("unLock: " + Thread.currentThread().getId());
//                lock.unlock();
//            }
//        }




    }

    @Resource
    private VoucherOrderService voucherOrderService;
    @Resource
    private VoucherService voucherService;
    @Resource
    private VoucherOrderMapper voucherOrderMapper;

    /**
     * 增加接口免费调用次数
     * @param interfaceInfoId
     * @param userId
     * @param voucherId
     * @return
     */
    @Override
    public boolean saveFreeLeftNums(long interfaceInfoId, long userId, long voucherId) {

        // 首先查询抵用券是否有效，就是订单是否已经被处理
        QueryWrapper<VoucherOrder> voucherOrderQueryWrapper = new QueryWrapper<>();
        voucherOrderQueryWrapper.eq("interfaceInfoId", interfaceInfoId).eq("userId", userId).eq("voucherId", voucherId);
        VoucherOrder voucherOrder = voucherOrderService.getOne(voucherOrderQueryWrapper);
        Integer status = voucherOrder.getStatus();
        if (status == 2) {
            // 直接返回
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        // 执行添加免费次数
        Voucher voucher = voucherService.getById(voucherId);
        UpdateWrapper<UserInterfaceInfo> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("interfaceInfoId", interfaceInfoId);
        updateWrapper.eq("userId", userId);
        updateWrapper.setSql("freeLeftNum = freeLeftNum + " + voucher.getFreeNums());
        boolean flag = this.update(updateWrapper);
        if (!flag) {
            log.info("添加失败");
            throw new BusinessException(ErrorCode.FORBIDDEN_ERROR);
        }
        // 添加成功,将订单置为已经使用
        boolean b = voucherOrderMapper.updateStatus(voucherOrder.getId());
        if (!b) {
            throw new BusinessException(ErrorCode.FORBIDDEN_ERROR);
        }
        // 然后执行兑换逻辑
        return true;
    }
}



